/* drawcircles.v
 *
 * Top level entity for the drawcircles circuits.
 * Inputs:
 * - SW[4:0] - a value for Y coordinate of the center of the circle (times 4 + 56). Should be between 0 and 31.
 * - SW[10:5] - a value for X coordinate of the center of the circle (times 4 + 32). Should be between 0 and 63.
 * - SW[13:11] - the colour of the circle to be drawn.
 * - SW[16:14] - the radius of the circle (times 4 + 1).
 * - SW[17] - toggle high to signal that the new circle is now ready.
 * - KEY[0] - asynchronous reset. Press the button to reset the system.
 * Outputs:
 * - circles display on a monitor
 * - LEDG[8] is lit up when new circle can be entered.
 */

module drawcircles(
			SW,
			CLOCK_50,
			LEDG,
			KEY,
			VGA_R,
			VGA_G,
			VGA_B,
			VGA_HS,
			VGA_VS,
			VGA_BLANK,
			VGA_SYNC,
			VGA_CLK);
			
	input [17:0] SW;
	input [3:0] KEY;
	input CLOCK_50;
	output [8:0] LEDG;
	output [9:0] VGA_R;
	output [9:0] VGA_G;
	output [9:0] VGA_B;
	output VGA_HS,
			 VGA_VS,
			 VGA_BLANK,
			 VGA_SYNC,
			 VGA_CLK;		

	/* Local wires to connect modules together */
	wire circle_done, circle_go, ready;
	wire [2:0] colour;
	wire resetN, go;
	wire [8:0] to_VGA_x;
	wire [7:0] to_VGA_y;
	wire to_VGA_plot;
	wire [8:0] new_CX;
	wire [7:0] new_CY;
	wire [2:0] new_colour;
	wire [4:0] new_radius;
	wire       to_VGA_plot_edge;
	
	wire x_ge_y;
	wire error_ge_0;
	wire drawstate_eq_7;
	wire init;
	wire E_X_error, E_Y_error, Edrawstate;
	wire [2:0] ps;
	
	assign new_CX = 9'h20 + {1'b0, SW[10:5], SW[10:9]};
	assign new_CY = 8'h38 + {1'b0, SW[4:0], SW[4:3]};
	assign new_colour = SW[13:11];
	assign new_radius = {SW[16:14], 2'h1};
	assign go = SW[17];
	assign resetN = KEY[0];
	
	assign x_ge_y         = X >= Y;
	assign error_ge_0     = (error >= 7'b0) && ~error[6];
	assign drawstate_eq_7 = (drawstate == 3'b111);
	
	assign LEDG[2:0] = ps;
	assign LEDG[5:3] = drawstate;
	//assign LEDG[3]   = Edrawstate;
	assign LEDG[6]   = circle_done;
	assign LEDG[7]   = ~run_CDA;
	
	// Necesssary Registers
	reg signed [6:0] error;		//a bit larger than X/Y since error is often incremented by 2*X or 2*Y
	reg [4:0] X,Y;					//radius is 5 bits, X/Y can be a maximum of radius
	reg [2:0] drawstate;
	
	//temp assignments
	assign colour = new_colour;
	
	//posedge_Detector(CLOCK_50, to_VGA_plot, to_VGA_plot_edge);	
	
	vga_adapter VGA(
				.resetn(resetN),
				.clock(CLOCK_50),
				.colour(new_colour),
				.x(to_VGA_x),
				.y(to_VGA_y),
				.plot(to_VGA_plot),
				.VGA_R(VGA_R),
				.VGA_G(VGA_G),
				.VGA_B(VGA_B),
				.VGA_HS(VGA_HS),
				.VGA_VS(VGA_VS),
				.VGA_BLANK(VGA_BLANK),
				.VGA_SYNC(VGA_SYNC),
				.VGA_CLK(VGA_CLK));
			defparam VGA.RESOLUTION = "320x240";
			defparam VGA.MONOCHROME = "FALSE";
			defparam VGA.BITS_PER_COLOUR_CHANNEL = 1;
			defparam VGA.BACKGROUND_IMAGE = "background.mif";

			
	wire run_CDA;
	wire [8:0] ui_cx;
	wire [7:0] ui_cy;
	wire [2:0] ui_colour;
	wire [4:0] ui_radius;
	/* UI FSM */
	FSM_UI(
		.clock(CLOCK_50),
		.resetN(resetN),
		.lock(go),
		.CDA_done(circle_done),
		.cx_in(new_CX),
		.cy_in(new_CY),
		.colour_in(new_colour),
		.radius_in(new_radius),
		.run_CDA(run_CDA),
		.ui_CX(ui_cx),
		.ui_CY(ui_cy),
		.ui_Colour(ui_colour),
		.ui_Radius(ui_radius));
			
			
	/* Circle algorithm FSM */
	FSM CDA_FSM(
				.clock(CLOCK_50), 
				.resetN(resetN), 
				.go(run_CDA),
				.x_ge_y(x_ge_y), 
				.error_ge_0(error_ge_0),
				.drawstate_eq_7(drawstate_eq_7),
				.Done(circle_done), 
				.init(init),
				.E_X_error(E_X_error),
				.E_Y_error(E_Y_error),
				.plot(to_VGA_plot),
				.Edrawstate(Edrawstate),
				.ps(ps));
			
	drawstateMux(drawstate, X, ui_cx, to_VGA_x, Y, ui_cy, to_VGA_y);
	
	always@(posedge CLOCK_50) begin
			if (init) begin
				error <= -ui_radius;
				X <= ui_radius;
				Y <= 5'b0;
				drawstate <= 3'b111;
			end
			
			else if (E_X_error) begin
				error <= error - ({X,1'b0} - 6'b1);
				X <= X - 5'b1;
			end
			
			else if (E_Y_error) begin
				error <= error + {Y,1'b1}; 	//essentially 2Y+1
				Y <= Y + 5'b1;
			end
			
			else if (Edrawstate)
				drawstate <= drawstate + 3'b001;
	end
	
	/* User interface */
	
	/* Circuit outputs. */

endmodule
		
